package com.txazo.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.*;

import com.txazo.dao.BaseDao;

/**
 * JDBC通用Dao实现
 * 
 * @author txazo
 * @since 1.0
 * 
 */
public class BaseDaoImpl implements BaseDao {

	private Connection connection = null;
	private PreparedStatement preparedStatement = null;
	private ResultSet resultSet = null;

	public BaseDaoImpl(Connection connection) {
		this.connection = connection;
	}

	@Override
	public void executeUpdate(String sql, Object[] params) throws Exception {
		preparedStatement = connection.prepareStatement(sql);
		for (int i = 0; i < params.length; i++) {
			preparedStatement.setObject(i + 1, params[i]);
		}
		preparedStatement.executeUpdate();
	}

	@Override
	public <T> List<T> executeQuery(String sql, Class<T> objectClass,
			Object[] params) throws Exception {
		List<T> list = null;

		preparedStatement = connection.prepareStatement(sql);
		for (int i = 0; i < params.length; i++) {
			preparedStatement.setObject(i + 1, params[i]);
		}
		resultSet = preparedStatement.executeQuery();
		list = getResultList(objectClass, resultSet);

		if (resultSet != null) {
			resultSet.close();
		}

		return list;
	}

	/**
	 * 查询结果集封装
	 * 
	 * @param <T> 泛型
	 * @param objectClass 返回对象类型
	 * @param resultSet 游标
	 * @return 查询结果集
	 */
	private <T> List<T> getResultList(Class<T> objectClass, ResultSet resultSet) {
		List<T> list = new ArrayList<T>();

		try {
			Field[] fields = objectClass.getDeclaredFields();
			Map<String, Method> map = new HashMap<String, Method>();
			for (int i = 0; i < fields.length; i++) {
				String fieldName = fields[i].getName();
				String firstLetter = fieldName.substring(0, 1).toUpperCase();
				String setMethodName = "set" + firstLetter
						+ fieldName.substring(1);
				Method setMethod = objectClass.getMethod(setMethodName,
						new Class[] { fields[i].getType() });
				map.put(fieldName, setMethod);
			}
			Set<String> keySet = map.keySet();

			while (resultSet.next()) {
				T object = null;
				object = objectClass.getConstructor(new Class[] {})
						.newInstance(new Object[] {});
				for (String key : keySet) {
					map.get(key).invoke(
							object,
							new Object[] { resultSet.getObject(key
									.toLowerCase()) });
				}
				list.add(object);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	@Override
	public PreparedStatement getPreparedStatement() {
		return preparedStatement;
	}

}
